package cn.tedu.mall.aop;

import cn.tedu.mall.anno.CacheFind;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;

@Aspect
@Component
public class RedisAOP {
    private ObjectMapper objectMapper=new ObjectMapper();
    @Autowired
    private Jedis jedis;
    //有切入点和通知
    @Around("@annotation(cacheFind)")
    public Object around(ProceedingJoinPoint joinPoint,CacheFind cacheFind) {
       //1.动态的获取key
        String key=getKey(joinPoint,cacheFind);
        //2.基于key到redis中查询数据
        String json = jedis.get(key);
        Object returnObject=null;
        //3.判断json是否为空
        if(StringUtils.isEmpty(json)){
            //说明第一次查询数据
            try {
                returnObject=joinPoint.proceed();//让目标方法进行执行
                //将数据封装到redis中，k-v
                String objJson = objectMapper.writeValueAsString(returnObject);
                if (cacheFind.seconds()>0){
                    //说明设置了redis缓存数据的超时时间的
                    jedis.setex(key,cacheFind.seconds(),objJson);
                }else {
                    jedis.set(key,objJson);
                }

            } catch (Throwable throwable) {
                throwable.printStackTrace();
                throw new RuntimeException();
            }
            System.out.println("AOP查询数据库");
        }else {
            //说明查询数据已经在redis服务器中存在了，直接获取即可
            //将json转换成List
           try {
               Class<?> targetClass=getClass(joinPoint);
               returnObject=objectMapper.readValue(json,targetClass);
               System.out.println("AOP查询缓存");
           }catch (Throwable throwable){
               throwable.printStackTrace();
               throw new RuntimeException();
           }
        }
        return returnObject;
    }

    private Class<?> getClass(ProceedingJoinPoint joinPoint) {
        MethodSignature methodSignature=(MethodSignature) joinPoint.getSignature();
        return methodSignature.getReturnType();
    }

    /**
     * 调用方法动态获取key
     * 如果用户在CacheFind注解中是否定义了key，定义了就用用户自定义的key，如果没有用默认的
     */
    private String getKey(ProceedingJoinPoint joinPoint, CacheFind cacheFind) {
        if (!StringUtils.isEmpty(cacheFind.key())){
            //说明用户自己有key
            return cacheFind.key();
        }
        //key:包名.类名.方法名::第一个参数的值
        String className = joinPoint.getSignature().getDeclaringTypeName();//获取包名.类名
        //获取方法名
        String methodName = joinPoint.getSignature().getName();
        //获取第一个参数值
        String firstArgs = joinPoint.getArgs()[0].toString();
        return className+"."+methodName+"::"+firstArgs;
    }
}
